﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SchedulerControl.Adorners
{
    public partial class CursorPlane : UserControl, ICursor
    {
        /// <summary>
        /// The element representing the current cursor. Can be null if no cursor or one of the system cursors is selected
        /// </summary>
        FrameworkElement _currentCursor = null;

        /// <summary>
        /// The rotate transform of the current cursor, if any
        /// </summary>
        RotateTransform _rotate = null;

        /// <summary>
        /// The traslate transform of the current cursor, if any
        /// </summary>
        TranslateTransform _translate = null;

        CursorType _currentCursorType = CursorType.None;
        bool _cursorSetOnce = false;

        /// <summary>
        /// The element used to display system cursors
        /// </summary>
        FrameworkElement _systemCursorElement = null;

        /// <summary>
        /// The current zoom level
        /// </summary>
        private double _zoomLevel = 1;

        private double _currentWidth = 1;
        private double _currentHeight = 1;

        public CursorPlane()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Sets the element used to display system cursors
        /// </summary>
        /// <param name="element"></param>
        public void SetSystemCursorElement(FrameworkElement element) {
            _systemCursorElement = element;
        }

        #region ICursor Members

        public void Show(CursorType type)
        {
            if ((_currentCursorType == type) && (_cursorSetOnce))
            {
                return;
            }

            _cursorSetOnce = true;

            if (_currentCursor != null) // if there was a non-system cursor previously visible
            {
                _currentCursor.Visibility = Visibility.Collapsed;
            }

            _currentCursor = null;
            _translate = null;
            _rotate = null;
            _currentCursorType = type;
            Cursor cursor = Cursors.None;

            switch (type)
            {
                case CursorType.None:
                    cursor = Cursors.None;
                    break;

                case CursorType.Default:
                case CursorType.SystemArrow:
                    cursor = Cursors.Arrow;
                    break;

                case CursorType.SystemEraser:
                    cursor = Cursors.Eraser;
                    break;

                case CursorType.SystemHand:
                    cursor = Cursors.Hand;
                    break;

                case CursorType.SystemIBeam:
                    cursor = Cursors.IBeam;
                    break;

                case CursorType.SystemSizeNS:
                    cursor = Cursors.SizeNS;
                    break;

                case CursorType.SystemSizeWE:
                    cursor = Cursors.SizeWE;
                    break;

                case CursorType.SystemStylus:
                    cursor = Cursors.Stylus;
                    break;

                case CursorType.SystemWait:
                    cursor = Cursors.Wait;
                    break;

                case CursorType.Size:
                    _currentCursor = pathSize;
                    _translate = pathSizeTranslate;
                    _rotate = pathSizeRotate;
                    break;

                case CursorType.Rotate:
                    _currentCursor = pathRotate;
                    _translate = pathRotateTranslate;
                    _rotate = pathRotateRotate;
                    break;

                case CursorType.Move:
                    _currentCursor = pathMove;
                    _translate = pathMoveTranslate;
                    break;

                case CursorType.Brush:
                    _currentCursor = paneBrush;
                    _translate = pathBrushTranslate;
                    break;

                case CursorType.SelectionBrush:
                    _currentCursor = paneSelectionBrush;
                    _translate = pathSelectionBrushTranslate;
                    break;

                case CursorType.Crosshair:
                    _currentCursor = pathCrosshair;
                    _translate = pathCrosshairTranslate;
                    break;

                case CursorType.MarkerSelect:
                    _currentCursor = paneMarkerSelect;
                    _translate = paneMarkerSelectTranslate;
                    break;

                default:
                    throw new ArgumentException("Unknown cursor type: " + type.ToString());
            }

            if (_currentCursor != null) {
                _currentCursor.Visibility = Visibility.Visible;
            }
            
            // update the system cursor accordingly
            _systemCursorElement.Cursor = cursor;
        }

        public void SetSize(double width, double height)
        {
            _currentWidth = width;
            _currentHeight = height;
            UpdateSize();
        }

        public double Zoom
        {
            get
            {
                return _zoomLevel;
            }
            set
            {
                _zoomLevel = value;
                UpdateSize();
            }
        }

        private void UpdateSize() {
            if (_currentCursor == null) // if doesn't support resize
            {
                return;
            }
            double w = _currentWidth * _zoomLevel;
            double h = _currentHeight * _zoomLevel;
            _currentCursor.Width = w;
            _currentCursor.Height = h;
            _sizeThickness.Left = -w / 2;
            _sizeThickness.Top = -h / 2;
            _currentCursor.Margin = _sizeThickness;
        }

        Thickness _sizeThickness = new Thickness();

        public void SetPos(double x, double y)
        {
            if (_translate == null) // if doesn't support position change
            {
                return;
            }
            _translate.X = x;
            _translate.Y = y;
        }

        public void SetAngle(double angleDegrees)
        {
            if (_rotate == null) // if doesn't support rotation
            {
                return;
            }
            _rotate.Angle = angleDegrees;
        }

        #endregion

    }
}
